/**
 * 
 */
package snooker.scoreboard.persistence;

import java.util.LinkedList;
import java.util.List;

import snooker.scoreboard.Match;
import snooker.scoreboard.entity.Type;
import snooker.scoreboard.frame.Frame;
import snooker.scoreboard.frame.FrameScoreHistory;
import snooker.scoreboard.frame.Score;
import android.os.SystemClock;
import android.util.Log;

/**
 * @author Mozes
 *
 */
public class LineParser implements ILineParser {

	private static final String LOG_TAG 	= "LINE PARSER";

	private static final int FILE_FORMAT_VERSION_1 = 1;
	private static final int FILE_FORMAT_VERSION_2 = 2;
	private static final int FILE_FORMAT_VERSION_3 = 3;
	
	private String player1Name = null;
	private String player2Name = null;
	private int playerId = Match.PLAYER1;
	private int breakId = 0;
	private int actFrameId = -1;
	private int linecount = 0;
	private int player1FrameWins = 0;
	private int player2FrameWins = 0;
	private int player1Score = 0;
	private int player2Score = 0;
	private int fileFormatVersion = 0;
	private Score fScore = null;
	private String fileName = null;
	private List<Score> frameScores = new LinkedList<Score>();
	private List<Frame> frames = new LinkedList<Frame>();
	private long startTime;
	private SnookerSharedPreferences ssp;
	
	public LineParser(String fileName) {
		
		Log.i(LOG_TAG, "new LineParser() {");

		startTime = SystemClock.elapsedRealtime();
		
		ssp = SnookerSharedPreferences.getInstance();
		ssp.clean();
		
		this.fileName = fileName;
	}

	public boolean preProcessing(String line) {
		if (FileHandler.OLD_HEADER.equals(line)) {
			fileFormatVersion = FILE_FORMAT_VERSION_1;
		} else if (FileHandler.HEADER.equals(line)) {
			fileFormatVersion = FILE_FORMAT_VERSION_2;
		}
		if (fileFormatVersion == 0) {
			return false;
		}
		return true;
	}
	
	public boolean postProcessing() {
		ssp.commit();
		if (player1Name == null) {
			player1Name = "Player1";
		}
		if (player2Name == null) {
			player2Name = "Player2";
		}
		if (player1Score > player2Score) {
			player1FrameWins++;
		} else if (player2Score > player1Score) {
			player2FrameWins++;
		}
		Frame newFrame = new Frame(frames.size() + 1, 0, Match.PLAYER1, player1Score, player2Score,
				new FrameScoreHistory(frameScores));
		frames.add(newFrame);
		ssp.saveActFrameId(newFrame.getFrameId());
		if (frames.size() > 0) {
			Match match = Match.getCurrentMatch();
			match.setPlayer1Name(player1Name);
			match.setPlayer2Name(player2Name);
			match.newMatch(fileName, frames, player1FrameWins, player2FrameWins);
		} else {
			Log.i(LOG_TAG, "Lines " + linecount);
			return false;
		}
		Log.i(LOG_TAG, " Lines " + linecount);
		Log.i(LOG_TAG, " Load time is " + ((SystemClock.elapsedRealtime() - startTime)/1000) + "," + (startTime%1000)+ " s");
		return true;
	}
	
	public boolean processLine(String line) {
		linecount++;
		if (fileFormatVersion < FILE_FORMAT_VERSION_3) {
			String playerName = line.substring(0, line.indexOf(',')); 
			if (player1Name == null) {
				player1Name = playerName;
			} else if (!player1Name.equals(playerName) && player2Name == null) {
				player2Name = playerName;
			} 
			if (player1Name.equals(playerName)) {
				playerId = Match.PLAYER1;
			} else {
				playerId = Match.PLAYER2;
			}
			String cline = line.replaceFirst(playerName, Integer.toString(playerId));
			ssp.saveScore(cline);
			fScore = Score.getDeserializedScore(cline);
		}
		if (actFrameId == -1) {
			actFrameId = fScore.getFrameId();
		}
		if (actFrameId != fScore.getFrameId()) {
			List<Score> f = frameScores;
			Frame newFrame = new Frame(frames.size() + 1, breakId, playerId, player1Score, player2Score,
					new FrameScoreHistory(f));
			frames.add(newFrame);
			ssp.saveActFrameId(newFrame.getFrameId());
			frameScores = new LinkedList<Score>();
			if (player1Score > player2Score) {
				player1FrameWins++;
			} else if (player2Score > player1Score) {
				player2FrameWins++;
			}
			player1Score = 0;
			player2Score = 0;
		}
		if (( fScore.getType().equals(Type.Foul) && fScore.getPlayerId() == Match.PLAYER1) || 
				(!fScore.getType().equals(Type.Foul) &&  fScore.getPlayerId() == Match.PLAYER2)) {
			player2Score += fScore.getScore();
		} else {
			player1Score += fScore.getScore();
		}
		breakId = fScore.getBreakId();
		
		frameScores.add(fScore);
		if (actFrameId != fScore.getFrameId()) {
			actFrameId = fScore.getFrameId();
		}
		return true;
	}
}
